import { type Editor, Extension } from "@tiptap/react"
import { Plugin, PluginKey } from "@tiptap/pm/state"
import type { FileError, FileValidationOptions } from "../../utils"
import { filterFiles } from "../../utils"

type FileHandlePluginOptions = {
	key?: PluginKey
	editor: Editor
	onPaste?: (editor: Editor, files: File[], pasteContent?: string) => void
	onDrop?: (editor: Editor, files: File[], pos: number) => void
	onValidationError?: (errors: FileError[]) => void
} & FileValidationOptions

const FileHandlePlugin = (options: FileHandlePluginOptions) => {
	const { key, editor, onPaste, onDrop, onValidationError, allowedMimeTypes, maxFileSize } =
		options

	return new Plugin({
		key: key || new PluginKey("fileHandler"),

		props: {
			handleDrop(view, event) {
				event.preventDefault()
				event.stopPropagation()

				const { dataTransfer } = event

				if (!dataTransfer?.files.length) {
					return false
				}

				const pos = view.posAtCoords({
					left: event.clientX,
					top: event.clientY,
				})

				const [validFiles, errors] = filterFiles(Array.from(dataTransfer.files), {
					allowedMimeTypes,
					maxFileSize,
					allowBase64: options.allowBase64,
				})

				if (errors.length > 0 && onValidationError) {
					onValidationError(errors)
				}

				if (validFiles.length > 0 && onDrop) {
					onDrop(editor, validFiles, pos?.pos ?? 0)
				}

				return true
			},
			handlePaste(_, event) {
				// 如果没有文件，不处理
				if (!event.clipboardData?.files.length) {
					return false
				}

				// 阻止默认粘贴行为
				event.preventDefault()
				event.stopPropagation()

				const { clipboardData } = event

				const [validFiles, errors] = filterFiles(Array.from(clipboardData.files), {
					allowedMimeTypes,
					maxFileSize,
					allowBase64: options.allowBase64,
				})

				const html = clipboardData.getData("text/html")

				if (errors.length > 0 && onValidationError) {
					onValidationError(errors)
				}

				if (validFiles.length > 0 && onPaste) {
					onPaste(editor, validFiles, html)
				}

				return true
			},
		},
	})
}

export const FileHandler = Extension.create<Omit<FileHandlePluginOptions, "key" | "editor">>({
	name: "fileHandler",

	addOptions() {
		return {
			allowBase64: false,
			allowedMimeTypes: [],
			maxFileSize: 0,
		}
	},

	addProseMirrorPlugins() {
		return [
			FileHandlePlugin({
				key: new PluginKey(this.name),
				editor: this.editor,
				...this.options,
			}),
		]
	},
})
